//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of your Microsoft Windows CE
// Source Alliance Program license form.  If you did not accept the terms of
// such a license, you are not authorized to use this source code.
//
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2003 Intrinsyc Europe Ltd.
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2004 Siemens AG
//
// Version: 1.1.2.5
// Date:    11. Jan. 2006
//////////////////////////////////////////////////////////////////////////////
//
//
// (C) Copyright 2007 Marvell International Ltd.
//  All Rights Reserved
//


#pragma once

#define DEFAULT_COM_MASK (EV_RXCHAR | EV_RLSD | EV_ERR | EV_BREAK)

// Default API timeout (in msec)
#define TIMEOUT_API_DEFAULT         20000
#define TIMEOUT_CMD_INIT            20000

// Timeout for SIM initialization (only MC75, TC63)
#define SIMINIT_TIMEOUT			15000  

#define COM_INIT_INDEX              0
#define COM_REINIT_INDEX            0

#define SENDREGINIT(i) (i==COM_INIT_INDEX)

#define MAX_CBM_STRING    128

// Forward declarations
class CRilInstanceHandle;
class CComHandle;
class CMonitor;
class CSimToolkitHandling;
class CEonsHandling;
class CRsaHandling;

// API IDs
// WARNING: If you add or remove entries from this table,
// you MUST synchronize the change with the table in the registry
// which holds perf/timeout information about each API.
// Held in HKEY_LOCAL_MACHINE\Software\Microsoft\RIL\APIInfo\<ApiEnumId>

enum APIID {
    APIID_NONE                          = -1,
    APIID_GETSUBSCRIBERNUMBERS          = 0,
    APIID_GETOPERATORLIST,              // 1
    APIID_GETPREFERREDOPERATORLIST,     // 2
    APIID_ADDPREFERREDOPERATOR,         // 3
    APIID_REMOVEPREFERREDOPERATOR,      // 4
    APIID_GETCURRENTOPERATOR,           // 5
    APIID_REGISTERONNETWORK,            // 6
    APIID_UNREGISTERFROMNETWORK,        // 7
    APIID_GETREGISTRATIONSTATUS,        // 8
    APIID_GETCALLERIDSETTINGS,          // 9
    APIID_SETCALLERIDSTATUS,            // 10
    APIID_GETHIDEIDSETTINGS,            // 11
    APIID_SETHIDEIDSTATUS,              // 12
    APIID_GETDIALEDIDSETTINGS,          // 13
    APIID_SETDIALEDIDSTATUS,            // 14
    APIID_GETCLOSEDGROUPSETTINGS,       // 15
    APIID_SETCLOSEDGROUPSETTINGS,       // 16
    APIID_GETCALLFORWARDINGSETTINGS,    // 17
    APIID_ADDCALLFORWARDING,            // 18
    APIID_REMOVECALLFORWARDING,         // 19
    APIID_SETCALLFORWARDINGSTATUS,      // 20
    APIID_GETCALLWAITINGSETTINGS,       // 21
    APIID_SETCALLWAITINGSTATUS,         // 22
    APIID_SENDSUPSERVICEDATA,           // 23
    APIID_CANCELSUPSERVICEDATASESSION,  // 24
    APIID_DIAL,                         // 25
    APIID_ANSWER,                       // 26
    APIID_HANGUP,                       // 27
    APIID_SENDDTMF,                     // 28
    APIID_SETDTMFMONITORING,            // 29
    APIID_GETCALLLIST,                  // 30
    APIID_MANAGECALLS,                  // 31
    APIID_TRANSFERCALL,                 // 32
    APIID_GETLINESTATUS,                // 33
    APIID_GETAUDIOGAIN,                 // 34
    APIID_SETAUDIOGAIN,                 // 35
    APIID_GETAUDIODEVICES,              // 36
    APIID_SETAUDIODEVICES,              // 37
    APIID_GETAUDIOMUTING,               // 38
    APIID_SETAUDIOMUTING,               // 39
    APIID_GETHSCSDOPTIONS,              // 40
    APIID_SETHSCSDOPTIONS,              // 41
    APIID_GETHSCSDCALLSETTINGS,         // 42
    APIID_GETDATACOMPRESSION,           // 43
    APIID_SETDATACOMPRESSION,           // 44
    APIID_GETERRORCORRECTION,           // 45
    APIID_SETERRORCORRECTION,           // 46
    APIID_GETBEARERSERVICEOPTIONS,      // 47
    APIID_SETBEARERSERVICEOPTIONS,      // 48
    APIID_GETRLPOPTIONS,                // 49
    APIID_SETRLPOPTIONS,                // 50
    APIID_GETMSGSERVICEOPTIONS,         // 51
    APIID_SETMSGSERVICEOPTIONS,         // 52
    APIID_GETMSGCONFIG,                 // 53
    APIID_SETMSGCONFIG,                 // 54
    APIID_RESTOREMSGCONFIG,             // 55
    APIID_SAVEMSGCONFIG,                // 56
    APIID_READMSG,                      // 57
    APIID_DELETEMSG,                    // 58
    APIID_WRITEMSG,                     // 59
    APIID_SENDMSG,                      // 60
    APIID_SENDSTOREDMSG,                // 61
    APIID_SENDMSGACKNOWLEDGEMENT,       // 62
    APIID_GETUSERIDENTITY,              // 63
    APIID_GETPHONELOCKEDSTATE,          // 64
    APIID_UNLOCKPHONE,                  // 65
    APIID_GETLOCKINGSTATUS,             // 66
    APIID_SETLOCKINGSTATUS,             // 67
    APIID_CHANGELOCKINGPASSWORD,        // 68
    APIID_GETCALLBARRINGSTATUS,         // 69
    APIID_SETCALLBARRINGSTATUS,         // 70
    APIID_CHANGECALLBARRINGPASSWORD,    // 71
    APIID_GETEQUIPMENTINFO,             // 72
    APIID_GETEQUIPMENTSTATE,            // 73
    APIID_SETEQUIPMENTSTATE,            // 74
    APIID_GETPHONEBOOKOPTIONS,          // 75
    APIID_SETPHONEBOOKOPTIONS,          // 76
    APIID_READPHONEBOOKENTRIES,         // 77
    APIID_WRITEPHONEBOOKENTRY,          // 78
    APIID_DELETEPHONEBOOKENTRY,         // 79
    APIID_SENDSIMCMD,                   // 80
    APIID_SENDRESTRICTEDSIMCMD,         // 81
    APIID_GETSIMRECORDSTATUS,           // 82
    APIID_GETSIMTOOLKITPROFILE,         // 83
    APIID_SETSIMTOOLKITPROFILE,         // 84
    APIID_SENDSIMTOOLKITENVELOPECMD,    // 85
    APIID_FETCHSIMTOOLKITCMD,           // 86
    APIID_SENDSIMTOOLKITCMDRESPONSE,    // 87
    APIID_TERMINATESIMTOOLKITSESSION,   // 88
    APIID_GETCOSTINFO,                  // 89
    APIID_SETCOSTINFO,                  // 90
    APIID_GETSIGNALQUALITY,             // 91
    APIID_GETCELLTOWERINFO,             // 92
    APIID_DEVSPECIFIC,                  // 93
    APIID_GETDEVCAPS,                   // 94
    APIID_GETHIDECONNECTEDIDSETTINGS,   // 95
    APIID_SETHIDECONNECTEDIDSTATUS,     // 96
    APIID_GETUUSREQUIREDSTATUS,         // 97
    APIID_CLEARCCBSREGISTRATION,        // 98
    APIID_GETSYSTEMTIME,                    // 99
    APIID_GETGPRSCONTEXTLIST,               // 100
    APIID_SETGPRSCONTEXT,                   // 101
    APIID_DELETEGPRSCONTEXT,                // 102
    APIID_GETREQUESTEDQUALITYOFSERVICELIST, // 103
    APIID_SETREQUESTEDQUALITYOFSERVICE,     // 104
    APIID_DELETEREQUESTEDQUALITYOFSERVICE,  // 105
    APIID_GETMINIMUMQUALITYOFSERVICELIST,   // 106
    APIID_SETMINIMUMQUALITYOFSERVICE,       // 107
    APIID_DELETEMINIMUMQUALITYOFSERVICE,    // 108
    APIID_SETGPRSATTACHED,                  // 109
    APIID_GETGPRSATTACHED,                  // 110
    APIID_SETGPRSCONTEXTACTIVATED,          // 111
    APIID_GETGPRSCONTEXTACTIVATEDLIST,      // 112
    APIID_ENTERGPRSDATAMODE,                // 113
    APIID_GETGPRSADDRESS,                   // 114
    APIID_GPRSANSWER,                       // 115
    APIID_GETGPRSREGISTRATIONSTATUS,        // 116
    APIID_GETGPRSCLASS,                     // 117
    APIID_SETGPRSCLASS,                     // 118
    APIID_GETMOSMSSERVICE,                  // 119
    APIID_SETMOSMSSERVICE,                  // 120
    APIID_GETCBMSGCONFIG,                   // 121
    APIID_SETCBMSGCONFIG,                   // 122
    APIID_GETCURRENTADDRESSID,              // 123
    APIID_SETCURRENTADDRESSID,              // 124
    APIID_GETPACKETBYTECOUNT,               // 125
    APIID_RESETPACKETBYTECOUNT,             // 126
    APIID_GETCURRENTPRIVACYSTATUS,          // 127
    APIID_GETCURRENTSYSTEMTYPE,             // 128
    APIID_GETALLOPERATORSLIST,              // 129
    APIID_SETINITIALGPRSATTACHED,           // 130
    APIID_ENABLEDISABLEURCS,                // 131
    APIID_SAP,                              // 132
    APIID_QUERYUNREADSMS,		    // 133
    APIID_TOTAL                             // 134
};


// API information structure
struct APIINFO {
    DWORD dwTimeout;
};


// Structure used for specifying init strings
struct INITSTRING_DATA {
    LPCSTR szCmd;
    DWORD dwCmdOption;
};


//
//
//
class CRilHandle
{
public:
                    CRilHandle();
                    ~CRilHandle();

    BOOL            StartInit();
    void            FinishInit(CCommand* pInitCmd, BOOL bSucceeded);
    void            GeneralInitDone(BOOL bSucceeded);

    void            PrepareForReinit();
    BOOL            LaunchThreads();
    BOOL            FCancelSet() const;
    BOOL            WaitForInit(DWORD dwTimeout) const;
    BOOL            WaitForCommandOrCancel(COM_PORT_TYPE PortType);
    BOOL            WaitForResponseOrCancel(COM_PORT_TYPE PortType);
    BOOL            AddToList(CRilInstanceHandle* const pInstance);
    BOOL            RemoveFromList(CRilInstanceHandle* const pInstance);
    HRESULT         GetNextCmdID();
    void            SendReadyStateNotification(DWORD dwReadyState, BOOL fBroadcast);
    void            BroadcastNotification(CNotificationData*& rpnd);
    BOOL            BroadcastRealBlobNotification(const DWORD dwNotificationCode, const void* const pBlob,
                                                  const UINT cbBlob);
    BOOL            BroadcastDWORDBlobNotification(const DWORD dwNotificationCode, const DWORD dwBlob);
    BOOL            HandleRsp(COM_PORT_TYPE PortType, CCommand*& rpCmd, CResponse*& rpRsp, BOOL& rfHungUp, BOOL& rfRadioOff);
    BOOL            AppendReadBytes(COM_PORT_TYPE PortType, LPCSTR szBytes, UINT cbBytes);
    BOOL            InheritReadBytes(COM_PORT_TYPE PortType, CResponse* const pRsp);
    BOOL            GiveUpReadBytes(COM_PORT_TYPE PortType, LPSTR& rszBytes, UINT& rcbBytes);
    BOOL            RegisterWithCPM();
    void            GetAPIInfo(APIID apiid, APIINFO& rapii);
    CCheckPoint*    GetCheckPoint() const { return m_pCheckPoint; };
    CComHandle*     GetComDevice(COM_PORT_TYPE PortType) const { return m_pComDevice[PortType]; };
    void            SetLastCommandTimedOut(COM_PORT_TYPE PortType) { if (m_pReadBytes[PortType] && m_pReadBytes[PortType]->GetLength() > 0) m_fLastCommandTimedOut[PortType] = TRUE; };
    void            StartWaitingForRsp(COM_PORT_TYPE PortType, CCommand *pCmd) { m_fWaitingForRsp[PortType] = TRUE; m_pCurrCommand[PortType] = pCmd; };
    void            StopWaitingForRsp(COM_PORT_TYPE PortType) { m_fWaitingForRsp[PortType] = FALSE; };
    BOOL            FWaitingForRsp(COM_PORT_TYPE PortType) const { return m_fWaitingForRsp[PortType]; };
    BOOL            SetEmergencyMode(const BOOL fMode);
    BOOL            FInEmergencyMode() { SYNCBLOCK(m_csEmergency); return !!m_fEmergencyMode; };
    void            SetIgnoreNextNOCARRIER(BOOL fMode) { m_fIgnoreNextNOCARRIER = fMode; return; };
    BOOL            IsSMSURCInitPhase() {return m_fSMSURCInitPhase; };
    BOOL            IsSimulatedCLIPActive() {return m_fSimulatedCLIPActive; };
    void            SetSimulatedCLIPActive(BOOL fMode) { m_fSimulatedCLIPActive = fMode; return; };
    DWORD           ResponseThread(COM_PORT_TYPE PortType);
    DWORD           CommandThread(COM_PORT_TYPE PortType);
    DWORD           SimReadyThread();
    void            StartReadyStateQuery();
    void            StopReadyStateQuery();
    BOOL            HandleRxData(COM_PORT_TYPE PortType, char *szData, DWORD dwRead);
    BOOL            CheckAudioProfilesVersion(COM_PORT_TYPE PortType);
    BOOL            DownloadAudioProfiles(COM_PORT_TYPE PortType);
    BOOL            ExSendATCommand(COM_PORT_TYPE PortType, char *pszATCommand);
    BOOL            ExGetATResponse(COM_PORT_TYPE PortType, char *pszATResponse, UINT uiBufLen, DWORD dwTimeout, BOOL fIgnoreTimeout = FALSE);
    BOOL            ExParseSBNRResponse(char *pszResponse, UINT uiBufLen, PDWORD pdwVersion);
    BOOL            ExSendATCmdGetRsp(COM_PORT_TYPE PortType, char *pszATCommand, char *pszATResponse, UINT uiBufLen, DWORD dwTimeout, DWORD dwRetries, BOOL fIgnoreTimeout = FALSE);
    BOOL            FetchOwnNumber();
    BOOL            ExParseCGMMResponse(char *pszResponse, UINT uiBufLen);
    BOOL            CheckModemType(COM_PORT_TYPE PortType);
    BOOL            BandHandover(COM_PORT_TYPE PortType);
    BOOL            InitMicrophone(COM_PORT_TYPE PortType);
    BOOL            IsSIMReady() { return m_fSimReady; }
    DWORD           SIMUnlockThread();
    void            SetAudioTxDevice(DWORD dwTxDevice)  { m_dwAudioTxDevice = dwTxDevice; };
    void            SetAudioRxDevice(DWORD dwRxDevice)  { m_dwAudioRxDevice = dwRxDevice; };
    DWORD           GetAudioTxDevice() const    { return m_dwAudioTxDevice; };
    DWORD           GetAudioRxDevice() const    { return m_dwAudioRxDevice; };
    DWORD           AckSMSThread();
    void            DeleteLastDialedNumber() {m_szLastDialedNumber[0]='\0'; return;};
    void            SetLastDialedNumber(const char *szLastDialedNumber) {strcpy(m_szLastDialedNumber, szLastDialedNumber); return;};
    char*           GetLastDialedNumber() {return m_szLastDialedNumber;};
    BOOL            GetDataAllowed()  const { return m_fAllowData; };
    BOOL            BlockCommandPriority(DWORD dwPriority = MAXDWORD, BOOL fAbort = FALSE);
    BOOL            BlockCommandHandling(COM_PORT_TYPE PortType);
    BOOL            BlockCommandHandling();
    BOOL            UnblockCommandHandling(COM_PORT_TYPE PortType);
    BOOL            UnblockCommandHandling();
    void            EnterUSSDAnswerMode(COM_PORT_TYPE PortType);
    void            LeaveUSSDAnswerMode(COM_PORT_TYPE PortType, BYTE* pData, DWORD dwSize);
    void            CancelUSSDAnswerMode(COM_PORT_TYPE PortType);
    INT             GetPortInUSSDAnswerMode();
    CSimToolkitHandling* GetSimToolkit(void) { return m_pSimToolkitHandling; };
    CEonsHandling*  GetEons(void) { return m_pEonsHandling; };
    CRsaHandling*   GetRsa(void) { return m_pRsaHandling; };
    COM_PORT_TYPE   GetFreeAlternativeCmdPort(BOOL bAllowAuxDataPort);
    CCommand*       GetCurrentCommand(COM_PORT_TYPE PortType) { return (m_fWaitingForRsp[PortType] ?  m_pCurrCommand[PortType] : NULL); }
    void            SignalInternalSIMReady();
    void            SignalAbortInternalSIMReady();
    DWORD           GetRILInstanceNums() {return m_pInstances->GetElemsNum();}
    void            SetDataEvent()   { SetEvent(m_hDataEvent); }
    
private:
    static DWORD WINAPI CheckPPLMNThreadProc(LPVOID pVoid);
    static DWORD GetInitSMSTries();
    BOOL         WaitForSIMInit();

    HANDLE                          m_hInitEvent;
    HANDLE                          m_hCancelEvent;
    HANDLE                          m_hSimReadyEvent;
    HANDLE                          m_hAbortInternalSimReadyEvent;
    HANDLE                          m_hInternalSimReadyEvent;
    HANDLE                          m_hCmdThread[NUMBER_OF_PORTS];
    HANDLE                          m_hReadThread[NUMBER_OF_PORTS];
    DWORD                           m_dwCmdThreadID[NUMBER_OF_PORTS];
    DWORD                           m_dwReadThreadID[NUMBER_OF_PORTS];
    char                            m_szLastDialedNumber[MAX_ATCMD_LEN];
    BOOL                            m_fQuitReadyStateThread;
    BOOL                            m_fIgnoreNextNOCARRIER;
    BOOL                            m_fSimulatedCLIPActive;
    BOOL                            m_fSMSURCInitPhase;
    CCheckPoint*                    m_pCheckPoint;
    CMonitor*                       m_pMonitor;
    CDblList<CRilInstanceHandle>*   m_pInstances;
    HRESULT                         m_hrNextCmdID;
    CRITICAL_SECTION                m_cs;
    CRITICAL_SECTION                m_csCmdID;
    CRITICAL_SECTION                m_csEmergency;
    CComHandle*                     m_pComDevice[NUMBER_OF_PORTS];
    CBuffer*                        m_pReadBytes[NUMBER_OF_PORTS];
    APIINFO*                        m_rgpAPIInfo[APIID_TOTAL];
    DWORD                           m_fInited : 1;
    DWORD                           m_fFailedInit : 1;
    DWORD                           m_fWaitingForRsp[NUMBER_OF_PORTS];
    DWORD                           m_fEmergencyMode : 1;
    DWORD                           m_fSimReady : 1;
    CRITICAL_SECTION                m_csATTimeouts;
    DWORD                           m_fLastCommandTimedOut[NUMBER_OF_PORTS];
    CCommand*                       m_pCurrCommand[NUMBER_OF_PORTS];
    BOOL                            m_fUSSDAnswerMode[NUMBER_OF_PORTS];
    DWORD                           m_dwAudioTxDevice;
    DWORD                           m_dwAudioRxDevice;
    HANDLE                          m_hBlockCmdsEvent[NUMBER_OF_PORTS];
    HANDLE                          m_hBlockRspsEvent[NUMBER_OF_PORTS];
    DWORD                           m_dwPendingPortCalls[NUMBER_OF_PORTS];
    CRITICAL_SECTION                m_csBlockCmds[NUMBER_OF_PORTS];
    volatile BOOL                   m_fAllowData;
    CSimToolkitHandling*            m_pSimToolkitHandling;
    CEonsHandling*                  m_pEonsHandling;
    CRsaHandling*                   m_pRsaHandling;
    HANDLE                          m_hDataEvent;     
};


typedef CUnboundedQueue<RILDRVNOTIFICATION> CRilNotificationQueue;

class CRilInstanceHandle : public CListElem
{
public:
                        CRilInstanceHandle();
                        ~CRilInstanceHandle();

    BOOL                Init(CRilHandle* const pDevice);
    void                Notify(const DWORD dwCode, const HRESULT hrCmdID, const void* const pBlob, const UINT cbBlob);
    BOOL                GetNextNotification(RILDRVNOTIFICATION& rrdnNotifyData);
    BOOL                CreateNotificationQueue(LPCTSTR tszEventName, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut);
    BOOL                FReadyForNotifications() const  { return !!m_fInited && m_notificationQ.Ready(); };
    CRilHandle*         GetDevice() const               { TBD_ASSERT(FALSE != !!m_fInited); return m_pDevice; };
    CDblList<CCommand>* GetCmdList() const              { TBD_ASSERT(FALSE != !!m_fInited); return m_pCmdList; };
    BOOL                MakePreferred();
    BOOL                FPreferred() const              { return !!m_fPreferred; };
    void                CancelNotifications() const     { if (m_hNotifyCancelEvent) {SetEvent(m_hNotifyCancelEvent);} }

private:
    CRilHandle*                     m_pDevice;
    CDblList<CCommand>*             m_pCmdList;
    HANDLE                          m_hNotifyCancelEvent;
    CRilNotificationQueue           m_notificationQ;
    DWORD                           m_fInited : 1;
    DWORD                           m_fPreferred : 1;
};

// Externs
extern const LPCTSTR g_tszRegKeyRIL;
extern const LPCTSTR g_tszRegKeyAPIInfo;
extern const LPCTSTR g_tszRegKeyOperNames;

extern DWORD g_TimeoutCmdInit;
extern DWORD g_TimeoutAPIDefault;

extern BOOL g_fReceiveCellBroadCast;
extern char g_szReceiveCellBroadCastChannels[MAX_CBM_STRING];
extern char g_szReceiveCellBroadCastDCS[MAX_CBM_STRING];

#define EV_RHA_CALLBACK_EVENTNAME (TEXT("EV_RHA_CALLBACK"))

#ifdef WANT_FILE_RILDRV_OUTPUT
extern int DbgWrite(LPWSTR lpszFmt, ...);
#endif  // DEBUG_FILE

#ifdef WANT_RILDRV_OUTPUT_TIMESTAMP
extern void NKDbgWithTimeStamp(LPWSTR lpszFmt, ...);
#endif
